package com.liao.ticket.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.liao.ticket.common.exception.ErrorCode;
import com.liao.ticket.dao.dos.ViewManager;
import com.liao.ticket.dao.mapper.FlightMapper;
import com.liao.ticket.dao.pojo.Flight;
import com.liao.ticket.dao.pojo.Seat;
import com.liao.ticket.dao.pojo.User;
import com.liao.ticket.service.FlightService;
import com.liao.ticket.service.SeatService;
import com.liao.ticket.util.*;
import com.liao.ticket.vo.FlightVo;
import com.liao.ticket.vo.Result;
import com.liao.ticket.vo.params.FlightParams;
import com.liao.ticket.vo.params.PageParams;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

@Service
public class FlightServiceImpl implements FlightService {
    @Autowired
    private FlightMapper flightMapper;

    @Autowired
    private SeatService seatService;

    @Override
    public Result selectOneById(Long id) {
        if (id == null) {
            return Result.fail(ErrorCode.FLIGHT_QUERY_PARAMS_FAIL);
        }
        LambdaQueryWrapper<Flight> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Flight::getType, 0).eq(Flight::getId, id);
        Flight flight = flightMapper.selectOne(wrapper);
        if (flight == null) {
            return Result.fail(ErrorCode.USER_NO_EXIT);
        }
        FlightVo flightVo = copy(flight);
        if(flightVo == null){
            return Result.fail(ErrorCode.FLIGHT_GLOBAL_NO_SEAT_EXIT);
        }
        return Result.success(flightVo);
    }

    @Override
    public Result selectListByFidAndTidAndFlyTime(FlightParams flightParams, PageParams pageParams) {
        String flyTime = flightParams.getFlyTime();
        Long airportFlyId = flightParams.getAirportFlyId();
        Long airportToId = flightParams.getAirportToId();
        if (airportFlyId == null || airportToId == null) {
            return Result.fail(ErrorCode.FLIGHT_QUERY_PARAMS_FAIL);
        }
        LambdaQueryWrapper<Flight> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Flight::getType, 0)
                .eq(Flight::getAirportFlyId,airportFlyId)
                .eq(Flight::getAirportToId,airportToId)
                .gt(Flight::getFlyTime,new Timestamp(DateUtils.toLongDay(flyTime,0)))
                .lt(Flight::getFlyTime,new Timestamp(DateUtils.toLongDay(flyTime,1)));
        Page<Flight> flightPage = flightMapper.selectPage(new Page<Flight>(pageParams.getPage(), pageParams.getPageSize()), wrapper);
        List<Flight> flightList = flightPage.getRecords();
        return Result.success(copy(flightList));
    }

    @Override
    public Flight findOneById(Long flightId) {
        return flightMapper.selectById(flightId);
    }

    @Override
    public Result addOne(FlightParams flightParams) {
        Long mid = CheckPowerUtils.getMid(0);
        if(mid == null){
            return Result.fail(ErrorCode.USER_NO_POWER);
        }
        Flight flight = new Flight();
        BeanUtils.copyProperties(flightParams,flight);
        flight.setId(null);
        flight.setFlyTime(new Timestamp(DateUtils.toLongMinutes(flightParams.getFlyTime(),0)));
        flight.setToTime(new Timestamp(DateUtils.toLongMinutes(flightParams.getToTime(), 0)));
        flight.setType(0);
        int insert = flightMapper.insert(flight);
        if(insert <= 0){
            return Result.fail(ErrorCode.FLIGHT_ADD_ERROR);
        }
        return Result.success(copy(flight));
    }

    @Override
    public Result updateOneAll(FlightParams flightParams) {
        Long mid = CheckPowerUtils.getMid(0);
        if(mid == null){
            return Result.fail(ErrorCode.USER_NO_POWER);
        }
        if (flightParams.getId() == null) {
            return Result.fail(ErrorCode.FLIGHT_UPDATE_PARAMS_FAIL);
        }
        Flight flight = new Flight();
        BeanUtils.copyProperties(flightParams,flight);
        flight.setId(flightParams.getId());
        flight.setFlyTime(new Timestamp(DateUtils.toLongMinutes(flightParams.getFlyTime(),0)));
        flight.setToTime(new Timestamp(DateUtils.toLongMinutes(flightParams.getToTime(), 0)));
        int update = flightMapper.updateById(flight);
        return Result.success(update);
    }

    // 修改 航班 信息（航班名，起飞地，降落地，里程，起飞机场id，起飞机场名，降落机场id，降落机场名）   type 30
    @Override
    public Result updateOneForAirLine(FlightParams flightParams) {
        Long mid;
        if (!((mid=CheckPowerUtils.getMid(0)) != null || (mid=CheckPowerUtils.getMid(30)) != null)) {
            return Result.fail(ErrorCode.USER_NO_POWER);
        }
        if (flightParams.getId() == null) {
            return Result.fail(ErrorCode.FLIGHT_UPDATE_PARAMS_FAIL);
        }
        Flight flight = new Flight();
        flight.setName(flightParams.getName());
        flight.setFlyPlace(flightParams.getFlyPlace());
        flight.setToPlace(flightParams.getToPlace());
        flight.setMileage(flightParams.getMileage());
        flight.setAirportFlyId(flightParams.getAirportFlyId());
        flight.setAirportFlyName(flightParams.getAirportFlyName());
        flight.setAirportToId(flightParams.getAirportToId());
        flight.setAirportToName(flightParams.getAirportToName());
        int update = flightMapper.update(flight,wrapper(flightParams.getId(),mid,UserThreadLocal.get().getType()));
        return Result.success(update);
    }

    @Override
    public Result deleteOne(Long id) {
        Long mid = CheckPowerUtils.getMid(0);
        if(mid == null) {
            return Result.fail(ErrorCode.USER_NO_POWER);
        }
        if (id == null) {
            return Result.fail(ErrorCode.FLIGHT_DELETE_PARAMS_FAIL);
        }
        return Result.success(flightMapper.deleteById(id));
    }

    // 修改 航班 信息（起飞时间，降落时间，状态）   type 20 30
    @Override
    public Result updateOneInfoForManager(FlightParams flightParams) {
        Long mid ;
        if(!((mid=CheckPowerUtils.getMid(0)) != null || (mid=CheckPowerUtils.getMid(20)) != null || (mid=CheckPowerUtils.getMid(30)) != null)) {
            return Result.fail(ErrorCode.USER_NO_POWER);
        }
        if (flightParams.getId() == null) {
            return Result.fail(ErrorCode.FLIGHT_UPDATE_PARAMS_FAIL);
        }
        Flight flight = new Flight();
        flight.setFlyTime(new Timestamp(DateUtils.toLongMinutes(flightParams.getFlyTime(),0)));
        flight.setToTime(new Timestamp(DateUtils.toLongMinutes(flightParams.getToTime(), 0)));
        flight.setType(flightParams.getType());
        return Result.success(flightMapper.update(flight,wrapper(flightParams.getId(),mid,UserThreadLocal.get().getType())));
    }

    // 修改 航班 状态     type 20 30
    @Override
    public Result updateOneTypeForManager(FlightParams flightParams) {
        Long mid ;
        if(!((mid=CheckPowerUtils.getMid(0)) != null || (mid=CheckPowerUtils.getMid(20)) != null || (mid=CheckPowerUtils.getMid(30)) != null)) {
            return Result.fail(ErrorCode.USER_NO_POWER);
        }
        if (flightParams.getId() == null) {
            return Result.fail(ErrorCode.FLIGHT_UPDATE_PARAMS_FAIL);
        }
        Flight flight = new Flight();
        flight.setType(flightParams.getType());
        return Result.success(flightMapper.update(flight,wrapper(flightParams.getId(),mid,UserThreadLocal.get().getType())));
    }

    @Override
    public Flight selectOneByFidAndMid(Long flightId, Long mid) {
        LambdaQueryWrapper<Flight> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Flight::getAirlineId, mid).eq(Flight::getId, flightId);
        return flightMapper.selectOne(wrapper);
    }

    private LambdaQueryWrapper<Flight> wrapper(Long id,Long mid,Integer type) {
        type = type/10*10;
        LambdaQueryWrapper<Flight> wrapper = new LambdaQueryWrapper<>();
        if (id != null) {
            wrapper.eq(Flight::getId, id);
        }
        if(mid != null && type != 0){
            if(type == 20){
                wrapper.and(con -> con.eq(Flight::getAirportFlyId,mid).or().eq(Flight::getAirportToId,mid));
            }else if(type == 30){
                wrapper.eq(Flight::getAirlineId, mid);
            }
        }
        return wrapper;
    }

    private FlightVo copy(Flight flight) {
        FlightVo flightVo = new FlightVo();
        BeanUtils.copyProperties(flight, flightVo);
        flightVo.setFlyDate(DateUtils.toStringMinutes(flight.getFlyTime(),0));
        flightVo.setToDate(DateUtils.toStringMinutes(flight.getToTime(),0));
        List<Seat> seatList = seatService.selectListByFid(flight.getId());
        if(seatList.size() == 0){
            return null;
        }
        flightVo.setSeatList(seatList);
        return flightVo;
    }

    private List<FlightVo> copy(List<Flight> flightList){
        List<FlightVo> flightVoList = new ArrayList<>();
        FlightVo flightVo;
        for (Flight flight : flightList) {
            flightVo = copy(flight);
            if(flightVo != null){
                flightVoList.add(flightVo);
            }
        }
        return flightVoList;
    }
}
